package cn.infrabase;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Weimin Gao
 * @since 1.0.0
 **/
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ErrorInfo {

	/**
	 * 错误代码
	 */
	private String code;

	/**
	 * 错误描述
	 */
	private String desc;

	/**
	 * 错误详情
	 */
	private String detail;

	@Override
	public String toString() {
		return "{" +
			"\"code\":" + toJson(code) + "," +
			"\"desc\":" + toJson(desc) + "," +
			"\"detail\":" + toJson(detail) +
			"}";
	}

	/**
	 * 返回错误信息对象。
	 *
	 * @param error 错误对象。
	 * @return 错误信息对象。
	 */
	public static ErrorInfo of(Error error) {
		return of(error.code(), error.desc(), error.detail());
	}

	/**
	 * 返回错误信息对象。
	 *
	 * @param error  错误对象。
	 * @param params 错误详情参数。
	 * @return 错误信息对象。
	 */
	public static ErrorInfo of(Error error, Object... params) {
		String detail = String.format(error.detail(), params);
		return of(error.code(), error.desc(), detail);
	}


	/**
	 * 构造函数。
	 *
	 * @param code   错误代码。
	 * @param desc   错误描述。
	 * @param detail 错误详情。
	 * @return 错误信息。
	 */
	private static ErrorInfo of(String code, String desc, String detail) {
		ErrorInfo ret = new ErrorInfo();
		ret.setCode(code);
		ret.setDesc(desc);
		ret.setDetail(detail);
		return ret;
	}

	// -----------------------------------------------------------------------------------------------------------------
	// 私有方法

	private static final String DOUBLE_QUOTES = "\"";

	private static final String LF = "\n";

	private static final String CR = "\n";

	private static String toJson(final String text) {
		if (text == null) {
			return "\"null\"";
		} else {
			String ret = text;
			if (ret.contains(DOUBLE_QUOTES)) {
				ret = ret.replaceAll(DOUBLE_QUOTES, "\\\\\"");
			}
			if (ret.contains(LF)) {
				ret = ret.replaceAll(LF, "\\\\n");
			}
			if (ret.contains(CR)) {
				ret = ret.replaceAll(CR, "\\\\r");
			}
			ret = "\"" + ret + "\"";
			return ret;
		}
	}

}
